package cn.peach.hrm.service.impl;

import cn.peach.hrm.constants.RedisConstants;
import cn.peach.hrm.dto.sendSmsCodeDto;
import cn.peach.hrm.service.IVerifyCodeService;
import cn.peach.hrm.to.SendVerifyCodeTo;
import cn.peach.hrm.util.AssertUtil;
import cn.peach.hrm.util.StrUtils;
import cn.peach.hrm.util.VerifyCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.elasticsearch.gateway.GatewayException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import static org.springframework.data.elasticsearch.annotations.FieldType.Date;

/**
 * @Author you
 * @create 2021/12/2 15:05
 */
@Service
@Slf4j
@Transactional
public class VerifyCodeServiceImpl implements IVerifyCodeService {

    @Autowired
    private RedisTemplate redisTemplate;

    /*1.后端收到请求，获取到KEY，生成图片验证码的值
     2.把图片验证码的值存储到Redis，以前段传入的key作为Redis的key
     3.把图片验证码的值合并到一个图片中
     4.把图片基于Base64编码层字符串，响应给前端*/
    /**
     * 生成图形验证码
     * @param key
     * @return
     */
    @Override
    public String imageCode(String key) {
        // 判断key是否为空
        AssertUtil.isNotEmpty(key,"错误请求");
        // 生成图形验证码
        String imageCode = StrUtils.getComplexRandomString(4);
        // 把图片验证码的值存储到Redis，以前段传入的key作为Redis的key
        redisTemplate.opsForValue().set(key, imageCode, 5L, TimeUnit.MINUTES);
        try {
            return VerifyCodeUtils.VerifyCode(130,35, imageCode);
        } catch (Exception e) {
            e.printStackTrace();
            throw new GatewayException("图形验证码生成失败");
        }
    }

    /**
     * 短信验证码
     * @param dto
     */
    @Override
    public void sendSmsCode(sendSmsCodeDto dto) {
        /** 发送短信验证码
        * 1.判断参数
        * 2.校验图片验证码
        * 2.1.拿到传入的KEY,去Redis获取图片验证码
        * 2.2.Redis图片验证码和传入的图片验证码做比较
        * 3.如果有上一次
        * 3.1.从Redis获取到上一次发送记录
        * 3.2.判断当前时间 - 上一次发送时间 时候大于60S
        * 3.3.获取到上一次的验证码作为此次发送的验证码
        * 4.如果没有上一次，生成一个短信验证码(随机数)
        * 5.调用短信网关发送短信验证码
        * 6.把发送记录存储到Redis（内容：时间，验证码，手机号 ； KEY：REG:SMS:手机号）
        * 7.存储一个发送记录到数据库*/
        // 获取参数
        String imageCode = dto.getImageCode();
        String imageCodeKey = dto.getImageCodeKey();
        String mobile = dto.getMobile();
        // 判断参数
        AssertUtil.isNotEmpty(imageCode,"图形验证码不能为空");
        AssertUtil.isNotEmpty(imageCodeKey,"请求错误");
        AssertUtil.isNotEmpty(mobile,"手机号不能为空");
        // 拿到传入的KEY,去Redis获取图片验证码
        String imageCodeRedis = (String) redisTemplate.opsForValue().get(imageCodeKey);
        AssertUtil.isEqual(imageCodeKey, imageCodeRedis, "图形验证码输入错误");
        // 3.如果有上一次
        // 3.1.从Redis获取到上一次发送记录
        // 3.2.判断当前时间 - 上一次发送时间 时候大于60S
        // 3.3.获取到上一次的验证码作为此次发送的验证码
        // 如果有上一次
        String code = null;
        String key = String.format(RedisConstants.KEY_SMS_CODE, mobile);
        // 从redis中获取
        SendVerifyCodeTo  keySend = (SendVerifyCodeTo) redisTemplate.opsForValue().get(key);
        // 系统时间
        Long thisTime = new Date().getTime();
        if (keySend != null) {
            boolean cutTime = (thisTime - keySend.getTime()) / 1000 < 60;
            AssertUtil.isFalse(cutTime, "请求频繁，稍后再试");
            // 获取上一次的验证码再发送一次
            code = keySend.getCode();
        }else {
            // 如果没有上一次
            code = StrUtils.getRandomString(6);
        }
        // MQ异步发送短信验证码
        log.info("您的短信验证码为：{}，请在{}分钟内使用",code ,5L);
         // 发送记录储存到redis
        redisTemplate.opsForValue().set(key, new SendVerifyCodeTo(code, thisTime));
        // 存储一个发送记录到数据库
        // TODO
        // 删除图形验证码
        redisTemplate.delete(imageCodeKey);
    }
}
